package ig.finanzas;

import ig.finanzas.riesgo.FactorRiesgoPersonal;
import ig.util.ejb.IGBean;
import ig.util.excepciones.DatoInvalidoExcepcion;
import ig.util.excepciones.LogicaExcepcion;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import javax.naming.NamingException;

/**
 * Implementa los metodos y funciones de un contrato que puede ser atomizable y que representa
 * titulo de propiedad.
 * @author lfgarcia
 */
public class PosicionAccionBean extends ContratoBean {
    
    static final long serialVersionUID = 01;
    /**
     * @uml.property  name="unidades"
     */
    private double unidades;
    //private double valorCompra;
    /**
     * @uml.property  name="bursatil"
     */
    private boolean bursatil;
    /**
     * @uml.property  name="accionPK"
     * @uml.associationEnd
     */
    private AccionPK accionPK;
    
    private String tipo=null;
    
    public String getTipo() {
        return tipo;
    }
    
    public void setTipo(String tipo) {
        this.tipo = tipo;
    }
    
    
    /**
     * @return  Returns the unidades.
     * @uml.property  name="unidades"
     */
    public double getUnidades(){
        return unidades;
    }
    
    
        /*
        public double getValorCompra(){
                return valorCompra;
        }
         */
    
    
    /**
     * @return  Returns the bursatil.
     * @uml.property  name="bursatil"
     */
    public boolean getBursatil(){
        return bursatil;
    }
    
    
    /**
     * @return  Returns the accionPK.
     * @uml.property  name="accionPK"
     */
    public AccionPK getAccionPK(){
        return accionPK;
    }
    
    /**
     * Valora el contrato a una fecha especifica.
     * @param fecha
     * @return
     * @throws DatoInvalidoExcepcion Si la fecha es nula.
     * @throws LogicaExcepcion Si no hay suficiente informacion para determinar el valor vigente.
     */
    public double valorar(Date fecha) throws DatoInvalidoExcepcion, LogicaExcepcion{
        if (fecha == null)
            throw new DatoInvalidoExcepcion("La fecha especificada es nula.");
        
        if (valoresRegistrados == null)
            throw new LogicaExcepcion("La entidad no posee valores historicos registrados.");
        
        return valoresRegistrados.obtenerValorVigenteA(fecha, 0);
    }
    
    /**
     * Calcula el cambio esperado de la serie de valores registrados del contrato.
     * @param fecha
     * @param definidor
     * @return
     * @throws DatoInvalidoExcepcion Si alguno de los parametros recibidos es invalido.
     * @throws LogicaExcepcion Si la forma de calculo no permite obtener el valor, si no hay suficientes
     * valores en la serie, si la informacion hallada no alcanza a ser una muestra estadisticamente representativa,
     * o si la serie no permite el calculo utilizando diferencias logaritmicas.
     */
    public double cambioEsperadoValoresRegistrados(Date fecha, DefinidorCalculoCambioEsperado definidor,boolean isPrecio) throws DatoInvalidoExcepcion, LogicaExcepcion{
        try{
            return valoresRegistrados.cambioEsperado(fecha, definidor,isPrecio);
        } catch (LogicaExcepcion e) {
            throw new LogicaExcepcion(" Posiciones Acciones "+e.toString());
        }
    }
    
    
    /**
     * Calcula el valor en riesgo del contrato.
     * @param fecha
     * @param factor
     * @return
     * @throws DatoInvalidoExcepcion Si la fecha o factor especificado es nulo, o si el
     * factor de riesgo definido no es de tipo precio.
     * @throws LogicaExcepcion Si la forma de calculo no permite obtener el valor, si no hay suficientes
     * valores en la serie, si la informacion hallada no alcanza a ser una muestra estadisticamente representativa,
     * o si la serie no permite el calculo utilizando diferencias logaritmicas.
     */
    public double valorEnRiesgo(Date fecha, FactorRiesgoPersonal factor,boolean isPrecio) throws DatoInvalidoExcepcion, LogicaExcepcion{
        
        /*try {
            this.cargarEntidad();
        } catch (Exception ex) {
            throw new LogicaExcepcion(ex.toString());
        }*/
        
        if (fecha == null)
            throw new DatoInvalidoExcepcion("La fecha especificada es nula.");
        
        if (factor==null)
            throw new DatoInvalidoExcepcion("El factor de riesgo suministrado es nulo.");
        
//		if (factor.getTipo()!=FactorRiesgoPersonal.TIPO_FACTORPRECIO)
//			throw new DatoInvalidoExcepcion("El factor de riesgo debe ser de tipo precio.");
        
        double cambioesperado = 0;
        if (factor.getTipoCalculoCambioEsperado()==FactorRiesgoPersonal.CAMBIOESPERADO_FACTORMATRIZ)
            cambioesperado = factor.getFactorRiesgoMatrizCorrelacion().getCambioEsperado();
        else
            cambioesperado = cambioEsperadoValoresRegistrados( fecha, factor.getDefinidorCalculoCambioEsperado(),isPrecio );
        
        double var = unidades * cambioesperado;
        
        /*if (!bursatil)
            var = var * 1.2;*/
        
        return var;
    }
    
    public void eliminarEntidad(){}
    
    public void actualizarEntidad(){}
    
    
    public void cargarEntidad() throws NamingException, DatoInvalidoExcepcion, SQLException{
        /*ContratoPK contratoPK = (ContratoPK)ctx.getPrimaryKey();
        long idInterna = contratoPK.getIdInterna();*/
        conn = IGBean.getMetricaDB();//getConexion("METRICADB");
        closeStatemente(pstmt1);
        pstmt1 = conn.prepareStatement(
                "SELECT UNIDADES, BURSATIL, TIPO, A.NOMBRE AS ACCION, IDACCION, M.NOMBRE AS MONEDA, M.ID AS IDMONEDA " +
                "FROM POSICIONESACCIONES P, ACCIONES A, MONEDAS M " +
                "WHERE P.IDACCION=A.ID AND A.IDMONEDA=M.ID AND P.ID=? ");
        pstmt1.setLong(1, pk.getIdInterna());
        
        ResultSet r1 = pstmt1.executeQuery();
        r1.next();
        
        int idAccion = r1.getInt("IDACCION");
        
        //Carga de atributos especificos
        this.unidades = r1.getDouble("UNIDADES");
        //this.valorCompra = r1.getDouble("VALORCOMPRA");
        this.bursatil = (r1.getInt("BURSATIL")==1?true:false);
        //carga el tipo
        this.tipo = r1.getString("TIPO");
        
        this.accionPK = new AccionPK(r1.getString("ACCION"));
        this.accionPK.setIdInterna(r1.getLong("IDACCION"));
        
        //Carga de atributos generales
        this.monedaPK = new MonedaPK(r1.getString("MONEDA"));
        this.monedaPK.setIdInterna(r1.getLong("IDMONEDA"));        
        pstmt1.close();
        
        cargarProductoPK(pk.getIdInterna());
        cargarFlujos(pk.getIdInterna());
        cargarValoresRegistrados(pk.getIdInterna(), unidades);
    }
    
    
    
    public ContratoPK ejbFindByPrimaryKey(ContratoPK pk) throws Exception{
        try{
            conn = IGBean.getMetricaDB();//getConexion("METRICADB");
            
            pstmt1 = conn.prepareStatement(
                    "SELECT ID " +
                    "FROM POSICIONESACCIONES " +
                    "WHERE ID=?");
            pstmt1.setLong(1, pk.getIdInterna());
            
            ResultSet r1=pstmt1.executeQuery();
            if (r1.next()==false)
                throw new Exception("No fue posible encontrar la posicion " + pk.toString());
            
            return pk;
            
        }catch(Exception e){
            throw new Exception("No fue posible cargar la posicion " + pk.toString() );
        }finally{
            try {
                if (pstmt1!=null) pstmt1.close();
            } catch (SQLException e) {}
            
//            try {
//                if (conn!=null) conn.close();
//            } catch (SQLException e) {}
        }
    }
    
    public List ejbFindAll() throws Exception{
        ArrayList contratos = new ArrayList();
        try{
            conn = IGBean.getMetricaDB();//getConexion("METRICADB");
            
            pstmt1 = conn.prepareStatement("SELECT * FROM POSICIONESACCIONES");
            ResultSet rs = pstmt1.executeQuery();
            
            while (rs.next()){
                PosicionAccionBean posicionAccionBean = new PosicionAccionBean();
                posicionAccionBean.tipo = rs.getString("TIPO");
                posicionAccionBean.unidades = rs.getDouble("UNIDADES");
                //posicionAccionBean.accionPK = rs.getDouble("UNIDADES");
                posicionAccionBean.setPk(new ContratoPK(-1L));
                posicionAccionBean.getPk().setIdInterna(rs.getLong("ID"));
                posicionAccionBean.cargarEntidad();
                contratos.add( posicionAccionBean );
            }
            
        }catch(Exception e){
            throw new Exception(e.toString());
        }finally{
            try {
                if (pstmt1!=null) pstmt1.close();
            } catch (SQLException e) {}
            
//            try {
//                if (conn!=null) conn.close();
//            } catch (SQLException e) {}
        }
        return contratos;
    }
    
}